home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / ICON_8 / ICONX_FO / OSET.C < prev    next >
Text File  |  1990-03-02  |  8KB  |  297 lines

  1. /*
  2.  * File: oset.c
  3.  *  Contents: compl, diff, inter, unions
  4.  */
  5.  
  6. #include "::h:config.h"
  7. #include "::h:rt.h"
  8. #include "rproto.h"
  9.  
  10. #ifdef PreProcess
  11. /* include(../M4/ops.m4) /* */
  12. /* */
  13. #endif                    /* PreProcess */
  14.  
  15. /*
  16.  * ~x - complement cset x.
  17.  */
  18.  
  19. OpDcl(compl,1,"~")
  20.    {
  21.    register int i;
  22.    union block *bp;
  23.    int *cs, csbuf[CsetSize];
  24.  
  25.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  26.       RunErr(0, NULL);
  27.  
  28.    /*
  29.     * Arg1 must be a cset.
  30.     */
  31.    if (cvcset(&Arg1, &cs, csbuf) == CvtFail) 
  32.       RunErr(104, &Arg1);
  33.  
  34.    /*
  35.     * Allocate a new cset and then copy each cset word from Arg1 
  36.     *  into the new cset words, complementing each bit.
  37.     */
  38.    bp = (union block *)alccset();
  39.    for (i = 0; i < CsetSize; i++) 
  40.        bp->cset.bits[i] = ~cs[i];
  41.    Arg0.dword = D_Cset;
  42.    BlkLoc(Arg0) = bp;
  43.    Return;
  44.    }
  45.  
  46. /*
  47.  * x -- y - difference of csets x and y or of sets x and y.
  48.  */
  49.  
  50. OpDcl(diff,2,"--")
  51.    {
  52.    register word i;
  53.    word slotnum;
  54.    register union block *srcp, *tstp, *dstp, **hook;
  55.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  56.    struct b_slots *seg;
  57.    struct b_selem *ep;
  58.  
  59.    if (Qual(Arg1) || Qual(Arg2))
  60.       goto skipsets;
  61.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  62.       RunErr(119, &Arg2);
  63.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  64.       RunErr(119, &Arg1);
  65.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  66.       /*
  67.        * Both Arg1 and Arg2 are sets - do set difference.  Make a new set
  68.        *  based on the size of Arg1.
  69.        */
  70.       dstp = hmake(T_Set, (word)0, BlkLoc(Arg1)->set.size);
  71.       if (dstp == NULL)
  72.          RunErr(0, NULL);
  73.       /*
  74.        * For each element in set Arg1 if it is not in set Arg2
  75.        *  copy it directly into the result set.
  76.        */
  77.       srcp = BlkLoc(Arg1);
  78.       tstp = BlkLoc(Arg2);
  79.       for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
  80.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  81.             ep = (struct b_selem *)seg->hslots[slotnum];
  82.             while (ep != NULL) {
  83.                memb(tstp, &ep->setmem, ep->hashnum, &res);
  84.                if (res == 0) {
  85.                   hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  86.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  87.                   }
  88.                ep = (struct b_selem *)ep->clink;
  89.                }
  90.             }
  91.       Arg0.dword = D_Set;
  92.       BlkLoc(Arg0) = dstp;
  93.       if (TooSparse(dstp))
  94.          hshrink(&Arg0);
  95.       }
  96.    else {
  97.       skipsets:
  98.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  99.       RunErr(0, NULL);
  100.  
  101.    /*
  102.     * Arg1 and Arg2 must be csets.
  103.     */
  104.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  105.       RunErr(120, &Arg1);
  106.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  107.       RunErr(120, &Arg2);
  108.  
  109.    /*
  110.     * Allocate a new cset and in each word of it, compute the value
  111.     *  of the bitwise difference of the corresponding words in the
  112.     *  Arg1 and Arg2 csets.
  113.     */
  114.    dstp = (union block *)alccset();
  115.    for (i = 0; i < CsetSize; i++) {
  116.       dstp->cset.bits[i] = cs1[i] & ~cs2[i];
  117.       }
  118.  
  119.    Arg0.dword = D_Cset;
  120.    BlkLoc(Arg0) = dstp;
  121.    }
  122.    Return;
  123.    }
  124.  
  125. /*
  126.  * x ** y - intersection of csets x and y or of sets x and y.
  127.  */
  128.  
  129. OpDcl(inter,2,"**")
  130.    {
  131.    register word i;
  132.    word slotnum;
  133.    register union block *srcp, *tstp, *dstp, **hook;
  134.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  135.    struct b_slots *seg;
  136.    struct b_selem *ep;
  137.  
  138.    if (Qual(Arg1) || Qual(Arg2))
  139.       goto skipsets;
  140.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  141.       RunErr(119, &Arg2);
  142.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  143.       RunErr(119, &Arg1);
  144.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  145.       /*
  146.        * Both Arg1 and Arg2 are sets - do set intersection.
  147.        *  Make a new set the size of the smaller argument set.
  148.        */
  149.       dstp = hmake(T_Set, (word)0,
  150.          Min(BlkLoc(Arg1)->set.size, BlkLoc(Arg2)->set.size));
  151.       if (dstp == NULL)
  152.          RunErr(0, NULL);
  153.       /*
  154.        * Using the smaller of the two sets as the source
  155.        *  copy directly into the result each of its elements
  156.        *  that are also members of the other set.
  157.        */
  158.       if (BlkLoc(Arg1)->set.size <= BlkLoc(Arg2)->set.size) {
  159.          srcp = BlkLoc(Arg1);
  160.          tstp = BlkLoc(Arg2);
  161.          }
  162.       else {
  163.          srcp = BlkLoc(Arg2);
  164.          tstp = BlkLoc(Arg1);
  165.          }
  166.       for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
  167.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  168.             ep = (struct b_selem *)seg->hslots[slotnum];
  169.             while (ep != NULL) {
  170.                memb(tstp, &ep->setmem, ep->hashnum, &res);
  171.                if (res != 0) {
  172.                   hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  173.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  174.                   }
  175.                ep = (struct b_selem *)ep->clink;
  176.                }
  177.             }
  178.       Arg0.dword = D_Set;
  179.       BlkLoc(Arg0) = dstp;
  180.       if (TooSparse(dstp))
  181.          hshrink(&Arg0);
  182.       }
  183.    else {
  184.       skipsets:
  185.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  186.       RunErr(0, NULL);
  187.  
  188.    /*
  189.     * Arg1 and Arg2 must be csets.
  190.     */
  191.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  192.       RunErr(120, &Arg1);
  193.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  194.       RunErr(120, &Arg2);
  195.  
  196.    /*
  197.     * Allocate a new cset and in each word of it, compute the value
  198.     *  of the bitwise intersection of the corresponding words in the
  199.     *  Arg1 and Arg2 csets.
  200.     */
  201.    dstp = (union block *)alccset();
  202.    for (i = 0; i < CsetSize; i++) {
  203.       dstp->cset.bits[i] = cs1[i] & cs2[i];
  204.       }
  205.  
  206.    Arg0.dword = D_Cset;
  207.    BlkLoc(Arg0) = dstp;
  208.    }
  209.    Return;
  210.    }
  211.  
  212. /*
  213.  * x ++ y - union of csets x and y or of sets x and y.
  214.  */
  215.  
  216. OpDcl(unions,2,"++")
  217.    {
  218.    register word i;
  219.    word slotnum;
  220.    register union block *srcp, *tstp, *dstp, **hook;
  221.    int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
  222.    struct b_slots *seg;
  223.    struct b_selem *ep;
  224.    dptr srcd, tstd;
  225.  
  226.    if (Qual(Arg1) || Qual(Arg2))
  227.       goto skipsets;
  228.    if (Arg1.dword == D_Set && Arg2.dword != D_Set) 
  229.       RunErr(119, &Arg2);
  230.    if (Arg2.dword == D_Set && Arg1.dword != D_Set) 
  231.       RunErr(119, &Arg1);
  232.    if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
  233.       /*
  234.        * Both Arg1 and Arg2 are sets - do set union.  Copy the larger set
  235.        *  and ensure there's room for *Arg1 + *Arg2 elements.
  236.        */
  237.       if (BlkLoc(Arg1)->set.size >= BlkLoc(Arg2)->set.size) {
  238.          srcd = &Arg1;
  239.          tstd = &Arg2;
  240.          }
  241.       else {
  242.          srcd = &Arg2;
  243.          tstd = &Arg1;
  244.          }
  245.       if (cpset(srcd, &Arg0, BlkLoc(Arg1)->set.size + BlkLoc(Arg2)->set.size)
  246.             == Error)
  247.          RunErr(0, NULL);
  248.       /*
  249.        * Copy each element from the smaller set into the result set,
  250.        *  if it is not already there.
  251.        */
  252.       srcp = BlkLoc(*srcd);
  253.       tstp = BlkLoc(*tstd);
  254.       dstp = BlkLoc(Arg0);
  255.       for (i = 0; i < HSegs && (seg = tstp->set.hdir[i]) != NULL; i++)
  256.          for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
  257.             ep = (struct b_selem *)seg->hslots[slotnum];
  258.             while (ep != NULL) {
  259.                hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
  260.                if (res == 0)
  261.                   addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
  262.                ep = (struct b_selem *)ep->clink;
  263.             }
  264.          }
  265.       if (TooCrowded(dstp))        /* if the union got too big, enlarge */
  266.          hgrow(&Arg0);
  267.       }
  268.    else {
  269.       skipsets:
  270.  
  271.    if (blkreq((word)sizeof(struct b_cset)) == Error)
  272.       RunErr(0, NULL);
  273.  
  274.    /*
  275.     * Arg1 and Arg2 must be csets.
  276.     */
  277.    if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail) 
  278.       RunErr(120, &Arg1);
  279.    if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail) 
  280.       RunErr(120, &Arg2);
  281.  
  282.    /*
  283.     * Allocate a new cset and in each word of it, compute the value
  284.     *  of the bitwise union of the corresponding words in the
  285.     *  Arg1 and Arg2 csets.
  286.     */
  287.    dstp = (union block *)alccset();
  288.    for (i = 0; i < CsetSize; i++) {
  289.       dstp->cset.bits[i] = cs1[i] | cs2[i];
  290.       }
  291.  
  292.    Arg0.dword = D_Cset;
  293.    BlkLoc(Arg0) = dstp;
  294.    }
  295.    Return;
  296.    }
  297.